﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SortGuid.Tool.Comb.Strategy
{
    public class UnixDateTimeStrategy : ICombDateTimeStrategy
    {
        private const long TicksPerMillisecond = 10000L;

        private int _numDateBytes = 6;

        public int NumDateBytes
        {
            get { return _numDateBytes; }
        }

        private DateTime _minDateTimeValue = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

        public DateTime MinDateTimeValue
        {
            get { return _minDateTimeValue; }
        }

        private DateTime _maxDateTimeValue = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(2 ^ (8 * 6));// NumDateBytes

        public DateTime MaxDateTimeValue
        {
            get { return _maxDateTimeValue; }
        }

        public byte[] DateTimeToBytes(DateTime timestamp)
        {
            long value = ToUnixTimeMilliseconds(timestamp);
            byte[] bytes = BitConverter.GetBytes(value);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse((Array)bytes);
            }

            byte[] array = new byte[NumDateBytes];
            int sourceIndex = bytes.GetUpperBound(0) + 1 - NumDateBytes;
            Array.Copy(bytes, sourceIndex, array, 0, NumDateBytes);
            return array;
        }

        public DateTime BytesToDateTime(byte[] value)
        {
            byte[] array = new byte[8];
            int destinationIndex = 8 - NumDateBytes;
            Array.Copy(value, 0, array, destinationIndex, NumDateBytes);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse((Array)array);
            }

            long ms = BitConverter.ToInt64(array, 0);
            return FromUnixTimeMilliseconds(ms);
        }

        public long ToUnixTimeMilliseconds(DateTime timestamp)
        {
            return (timestamp.Ticks - MinDateTimeValue.Ticks) / 10000;
        }

        public DateTime FromUnixTimeMilliseconds(long ms)
        {
            return MinDateTimeValue.AddTicks(ms * 10000);
        }
    }
}
